package cn.iocoder.yudao.framework.apilog.config;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.apilog.core.filter.ApiAccessLogFilter;
import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService;
import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
import cn.iocoder.yudao.framework.apilog.core.service.DefaultApiAccessLogFrameworkService;
import cn.iocoder.yudao.framework.apilog.core.service.DefaultApiErrorLogFrameworkService;
import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum;
import cn.iocoder.yudao.framework.web.config.WebProperties;
import cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.support.SpringFactoriesLoader;

import javax.servlet.Filter;
import java.util.List;

@AutoConfiguration(after = YudaoWebAutoConfiguration.class)
@Slf4j
public class YudaoApiLogAutoConfiguration {


    @Bean
    public ApiAccessLogFrameworkService apiAccessLogFrameworkService() {
        List<ApiAccessLogFrameworkService> apiAccessLogFrameworkServiceList = SpringFactoriesLoader.loadFactories(ApiAccessLogFrameworkService.class,
                Thread.currentThread().getContextClassLoader());
        if (CollUtil.isNotEmpty(apiAccessLogFrameworkServiceList)) {
            log.info("使用 {} 作为 apiAccessLogFrameworkService 实现类",apiAccessLogFrameworkServiceList.get(0).getClass().getName());
            return apiAccessLogFrameworkServiceList.get(0);
        } else {
            log.warn("没有发现具体apiAccessLogFrameworkService实现");
            return new DefaultApiAccessLogFrameworkService();
        }
    }

    @Bean
    public ApiErrorLogFrameworkService apiErrorLogFrameworkService() {
        List<ApiErrorLogFrameworkService> apiAccessLogFrameworkService = SpringFactoriesLoader.loadFactories(ApiErrorLogFrameworkService.class,
                Thread.currentThread().getContextClassLoader());
        if (CollUtil.isNotEmpty(apiAccessLogFrameworkService)) {
            log.info("使用 {} 作为 apiErrorLogFrameworkService 实现类",apiAccessLogFrameworkService.get(0).getClass().getName());
            return apiAccessLogFrameworkService.get(0);
        } else {
            log.warn("没有发现具体 apiErrorLogFrameworkService 实现");
            return new DefaultApiErrorLogFrameworkService();
        }
    }

    /**
     * 创建 ApiAccessLogFilter Bean，记录 API 请求日志
     */
    @Bean
    @ConditionalOnProperty(prefix = "yudao.access-log", value = "enable", matchIfMissing = true) // 允许使用 yudao.access-log.enable=false 禁用访问日志
    public FilterRegistrationBean<ApiAccessLogFilter> apiAccessLogFilter(WebProperties webProperties,
                                                                         @Value("${spring.application.name}") String applicationName,
                                                                         ApiAccessLogFrameworkService apiAccessLogFrameworkService) {
        if (apiAccessLogFrameworkService instanceof DefaultApiAccessLogFrameworkService) {
            log.warn("没有发现具体apiAccessLogFrameworkService实现，不注册日志记录拦截器");
            return null;
        }
        ApiAccessLogFilter filter = new ApiAccessLogFilter(webProperties, applicationName, apiAccessLogFrameworkService);
        return createFilterBean(filter, WebFilterOrderEnum.API_ACCESS_LOG_FILTER);
    }

    private static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) {
        FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter);
        bean.setOrder(order);
        return bean;
    }

}
